package moodish.server;


import java.util.ArrayList;
import java.util.LinkedList;

import moodish.comm.MoodishServerComm;
import moodish.comm.MoodishServerSideMessage;
import moodish.comm.ServerComm;
import moodish.server.MoodishServer;

/**
 * The server that:  keep track of who follows who and forward Mood messages accordingly; 
 * keep clients informed about who friends and unfriends them;
 * when a new client connects, the server send the list of currently connected user to that client so that the client will have an updated list of all currently connected users;
 * when a client connects or disconnects, the server sends a message with the appropriate information to all connected clients
 * @author Joao / Ricardo
 *
 */



public class Server implements MoodishServer {


	private ArrayList<User> listOfUsers = new ArrayList<User>();
	private ServerComm serverComm;

	@Override
	public void start(ServerComm serverComm1) {
		this.serverComm = serverComm1;
		serverComm.start();
		while (true) {

			if (serverComm.hasNextMessage()){

				MoodishServerSideMessage message = (MoodishServerSideMessage) serverComm.getNextMessage();


				/**
				 * When a client connects, the server send one {@link moodish.comm.ClientSideMessage.Type#CONNECTED CONNECTED} message 
				 * ({@link moodish.comm.ServerComm#sendClientConnected(String toNickname, String connectedNickname)
				 * ServerComm.sendClientConnected()}) for each connected client so that the newly connected client can maintain a list 
				 * of clients currently connected to the server. 
				 */

				if (message.getType() == MoodishServerSideMessage.Type.CLIENT_CONNECTED){
					System.out.println("O servidor recebeu uma mensagem do tipo: " + message.getType());
					boolean tempIsRegisteredUser = false;

					User newUser = new User(message.getClientNickname());
					newUser.setConnected();



					// 1) Warn every one that there is a new client 
					// 2) And send the list of online users to the new client


					for(User user : listOfUsers){
						System.out.println( user.getNickname());
						serverComm.sendClientConnected(user.getNickname(), newUser.getNickname());
						serverComm.sendClientConnected(newUser.getNickname(), user.getNickname());
					}
					listOfUsers.add(newUser);
				}

				/**
				 * 
				 *<p>
				 * When a client disconnects, all clients should be sent a {@link moodish.comm.ClientSideMessage.Type#DISCONNECTED DISCONNECTED} message 
				 * ({@link moodish.comm.ServerComm#sendClientDisconnected(String toNickname, String disconnectedNickname)
				 * ServerComm.sendClientDisconnected()}). When a client disconnects, it loses all its friends and automatically
				 * unfriends all other clients. The server should thus not maintain a memory server regarding friends of disconnected clients. 
				 */

				//checks if the message is type CLIENT_DISCONNECTED
				else if (message.getType() == MoodishServerSideMessage.Type.CLIENT_DISCONNECTED){
					System.out.println("O servidor recebeu uma mensagem do tipo: " + message.getType());
					User userLeaving = null;
					for(User user: listOfUsers){
						if(user.getNickname().equals(message.getClientNickname()))
							userLeaving = user;
					}

					listOfUsers.remove(userLeaving);

					for(User user: listOfUsers){
						serverComm.sendClientDisconnected(user.getNickname(), userLeaving.getNickname());
					}
				}

				//checks if the message is type MOODISH_MESSAGE
				else if (message.getType().equals(MoodishServerSideMessage.Type.MOODISH_MESSAGE)) {
					System.out.println("O servidor recebeu uma mensagem do tipo: " + message.getType());
					LinkedList<String> tempFriends = new LinkedList<String>();


					//search in list of User
					for (User user: listOfUsers){
						//search in friendsList
						for( String friendUser : user.getlistOffriends()) {
							//if the sender exists in the friendsList send the mood
							if(friendUser.equals(message.getClientNickname())){
								serverComm.sendMoodishMessage(message.getClientNickname(),  user.getNickname(), message.getPayload());
							}
						}
					}
				}

				//checks if the message is type FRIENDSHIP
				else if (message.getType().equals(MoodishServerSideMessage.Type.FRIENDSHIP)){
					System.out.println("O servidor recebeu uma mensagem do tipo: " + message.getType());
					for (User user: listOfUsers){
						if (user.getNickname().equals(message.getClientNickname())){

							//If not in his list of Following, it add him to the list and sends a sendNewFollowers message.
							if (!user.inTheListofFriends(message.getPayload())){ 

								user.addfriend(message.getPayload());
								serverComm.sendNewFriendship(message.getPayload(), message.getClientNickname());
							}
							else
								//if in the list, it sends one error message
								serverComm.sendError(message.getClientNickname(), "Already following the requested user");

						}
					}
				}

				//checks if the message is type UNFRIENDSHIP
				else if (message.getType() == MoodishServerSideMessage.Type.UNFRIENDSHIP){
					System.out.println("O servidor recebeu uma mensagem do tipo: " + message.getType());

					for (User user: listOfUsers){
						if (user.getNickname().equals(message.getClientNickname())){
							//If is in the list of users he his following, it removes and sends a message sendNewUnfollow
							if(user.inTheListofFriends(message.getPayload())){
								user.removeFriend(message.getPayload());
								serverComm.sendNewUnfriendship(message.getPayload(), message.getClientNickname());
							}
							else
								//Of not in the list, sends one error message
								serverComm.sendError(message.getClientNickname(), "Not following the requested user");
						}

					}

				}
				else {
					//If it sends one message that has no Type than the others, it sends one error message
					serverComm.sendError(message.getClientNickname(), "Erro - servico solicitado nao existente!!!!");
				}
			}
		}
	}

}
